package org.shanktech.tshare.binlogsync.facotry;

import java.util.List;

import org.shanktech.tshare.binlogsync.model.binlog.BinlogData;
import org.shanktech.tshare.binlogsync.model.binlog.DeleteBinglogData;
import org.shanktech.tshare.binlogsync.model.binlog.InsertBinlogData;
import org.shanktech.tshare.binlogsync.model.binlog.UpdateBinlogData;
import org.shanktech.tshare.binlogsync.process.parser.MixedModelParser;
import org.shanktech.tshare.binlogsync.process.parser.RowModelParser;
import org.shanktech.tshare.binlogsync.util.Constant.BinlogFormat;
import org.shanktech.tshare.binlogsync.util.Constant.SqlDML;
import org.springframework.util.CollectionUtils;

import com.google.code.or.binlog.BinlogEventV4;
import com.google.code.or.binlog.impl.event.DeleteRowsEvent;
import com.google.code.or.binlog.impl.event.QueryEvent;
import com.google.code.or.binlog.impl.event.UpdateRowsEvent;
import com.google.code.or.binlog.impl.event.WriteRowsEvent;
import com.google.code.or.common.glossary.Column;
import com.google.code.or.common.glossary.Pair;
import com.google.code.or.common.glossary.Row;

public class BinlogDataFactory {

  public static BinlogData getInstance(BinlogEventV4 event, String databaseName,
      String tableName) {
    BinlogData binlogData = null;
    if (event instanceof QueryEvent) {
      QueryEvent queryEvent = (QueryEvent) event;
      return getMixedBinlogData(queryEvent, databaseName, tableName);
    } else if (event instanceof UpdateRowsEvent) {

      UpdateRowsEvent updateRowsEvent = (UpdateRowsEvent) event;

      List<Pair<Row>> rows = updateRowsEvent.getRows();
      List<Column> colsAfter = null;
      List<Column> colsBefore = null;
      for (Pair<Row> p : rows) {
        colsAfter = p.getAfter().getColumns();
        colsBefore = p.getBefore().getColumns();
        break;
      }

      if (!CollectionUtils.isEmpty(colsBefore)
          && !CollectionUtils.isEmpty(colsAfter)) {
        UpdateBinlogData updateBinlogData =
            new UpdateBinlogData(colsAfter, databaseName, tableName,
                TableTransferFactory.getInstance(tableName),
                new RowModelParser(), BinlogFormat.ROW, null, colsBefore);

        binlogData = updateBinlogData;
      }
    } else if (event instanceof DeleteRowsEvent) {

      DeleteRowsEvent deleteRowsEvent = (DeleteRowsEvent) event;
      List<Row> rows = deleteRowsEvent.getRows();
      List<Column> columnList = null;
      for (Row row : rows) {
        columnList = row.getColumns();
        break;
      }

      if (!CollectionUtils.isEmpty(columnList)) {
        DeleteBinglogData deleteBinglogData =
            new DeleteBinglogData(columnList, databaseName, tableName,
                TableTransferFactory.getInstance(tableName),
                new RowModelParser(), BinlogFormat.ROW, null);

        binlogData = deleteBinglogData;
      }
    } else if (event instanceof WriteRowsEvent) {
      WriteRowsEvent wrtiteRowsEvent = (WriteRowsEvent) event;
      List<Column> columnList = null;
      for (Row row : wrtiteRowsEvent.getRows()) {
        columnList = row.getColumns();
        break;
      }

      if (!CollectionUtils.isEmpty(columnList)) {
        InsertBinlogData insertBinlogData =
            new InsertBinlogData(columnList, databaseName, tableName,
                TableTransferFactory.getInstance(tableName),
                new RowModelParser(), BinlogFormat.ROW, null);

        binlogData = insertBinlogData;
      }

    }
    return binlogData;
  }

  private static BinlogData getMixedBinlogData(QueryEvent event,
      String databaseName, String tableName) {
    BinlogData binlogData = null;
    String sql = event.getSql().toString();
    if (sql.indexOf(SqlDML.INSERT.getValue()) >= 0) {
      binlogData = new InsertBinlogData(null, databaseName, tableName,
          TableTransferFactory.getInstance(tableName), new MixedModelParser(),
          BinlogFormat.MIXED, sql);
    } else if (sql.indexOf(SqlDML.UPDATE.getValue()) >= 0) {
      binlogData = new UpdateBinlogData(null, databaseName, tableName,
          TableTransferFactory.getInstance(tableName), new MixedModelParser(),
          BinlogFormat.MIXED, sql, null);
    } else if (sql.indexOf(SqlDML.DELETE.getValue()) >= 0) {
      binlogData = new DeleteBinglogData(null, databaseName, tableName,
          TableTransferFactory.getInstance(tableName), new MixedModelParser(),
          BinlogFormat.MIXED, sql);
    }
    return binlogData;
  }
}
